package com.example.johnerez.myapplication;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by johnerez on 1/7/15.
 */
public class JsonMenuParser {
    public static DataTypes.Response parseResponse(String json) throws JSONException {
        JSONObject responseJson = new JSONObject(json);
        return new DataTypes.Response(
                parseRestaurantsArray(responseJson.optJSONArray("restaurant")), parseFiltersArray(responseJson.optJSONArray(("autofilter"))));
    }

    private static List<DataTypes.Restaurant> parseRestaurantsArray(JSONArray restaurantsJson)
            throws JSONException {
        List<DataTypes.Restaurant> restaurants = new ArrayList<>();
        if (restaurantsJson != null) {
            for (int i = 0; i < restaurantsJson.length(); i++) {
                restaurants.add(parseRestaurant(restaurantsJson.getJSONObject(i)));
            }
        }
        return restaurants;
    }

    private static List<String> parseFiltersArray(JSONArray filtersJson)
            throws JSONException {
        List<String> filters = new ArrayList<String>();
        if (filtersJson != null) {
            for (int i = 0; i < filtersJson.length(); i++) {
                filters.add(filtersJson.getString(i));
            }
        }
        return filters;
    }

    private static DataTypes.Restaurant parseRestaurant(JSONObject restaurantJson)
            throws JSONException {
        String name = restaurantJson.optString("name");

        List<DataTypes.Dish> dishes = parseDishesArray(restaurantJson.optJSONArray("menu_item"));
        List<DataTypes.Dish> matchingDishes =
                parseDishesArray(restaurantJson.optJSONArray("matching_menu_item"));

        String address = restaurantJson.optString("address");
        String phone = restaurantJson.optString("phone");

        double latitude = restaurantJson.optDouble("latitude");
        double longitude = restaurantJson.optDouble("longitude");

        double distanceKm = restaurantJson.optDouble("distance_km");

        int yelpRating = restaurantJson.optInt("yelp_rating");
        int yelpNumberOfRaters = restaurantJson.optInt("yelp_number_of_raters");

        int healthRating = restaurantJson.optInt("health_rating");

        List<DataTypes.Review> reviews = parseReviewsArray(restaurantJson.optJSONArray("review"));

        return new DataTypes.Restaurant(name, dishes, matchingDishes, address, phone, latitude,
                longitude, distanceKm, yelpRating, yelpNumberOfRaters, healthRating, reviews);
    }

    private static List<DataTypes.Dish> parseDishesArray(JSONArray menuItemsJson)
            throws JSONException {
        List<DataTypes.Dish> dishes = new ArrayList<>();
        if (menuItemsJson != null) {
            for (int i = 0; i < menuItemsJson.length(); i++) {
                dishes.add(parseDish(menuItemsJson.getJSONObject(i)));
            }
        }
        return dishes;
    }

    private static DataTypes.Dish parseDish(JSONObject dishJson) throws JSONException {
        return new DataTypes.Dish(getAndFixName(dishJson), dishJson.optDouble("price"),
                dishJson.optString("description"),
                dishJson.optString("image_url"), parseReviewsArray(dishJson.optJSONArray("review")));
    }

    private static String getAndFixName(JSONObject dishJson) {
        String name = dishJson.optString("name");
        if (name.charAt(2) == '.' || name.charAt(1) == '.') {
            if (name.charAt(2) == ' ' || name.charAt(3) == ' ') {
                name = name.substring(name.indexOf(' ') + 1);
            }
        }
        return name;
    }


    private static List<DataTypes.Review> parseReviewsArray(JSONArray reviewsJson)
            throws JSONException {
        List<DataTypes.Review> reviews = new ArrayList<>();
        if (reviewsJson != null) {
            for (int i = 0; i < reviewsJson.length(); i++) {
                reviews.add(parseReview(reviewsJson.getJSONObject(i)));
            }
        }
        return reviews;
    }

    private static DataTypes.Review parseReview(JSONObject reviewJson) throws JSONException {
        return new DataTypes.Review(reviewJson.optString("text"), reviewJson.optInt("rating"));
    }
}
